package com.zj.eswrapper.interfaces;

import java.util.Collection;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 分页以及排序等条件拼接器接口
 *
 * @author arthur_zhou
 * @date 2023/12/29 17:43
 */
public interface IESearchWrapper<Field, SearchWrapper extends IESearchWrapper<Field, SearchWrapper, SearchBuilder>, SearchBuilder>
        extends IBaseWrapper<Field> {

    /**
     * 限制条数
     *
     * @param from 起始下标
     * @return this
     */
    SearchWrapper from(Integer from);

    /**
     * 限制条数
     *
     * @param size 返回条数
     * @return this
     */
    SearchWrapper size(Integer size);

    /**
     * 限制条数
     *
     * @param from 起始下标
     * @param size 返回条数
     * @return this
     */
    SearchWrapper limit(Integer from, Integer size);

    /**
     * 查询字段
     *
     * @param field 字段名
     * @return this
     */
    default SearchWrapper select(Field... field) {
        return select(Objects.nonNull(field) ? Stream.of(field).map(this::getField).collect(Collectors.toList()) : null);
    }

    /**
     * 查询字段
     *
     * @param fields 字段名集合
     * @return this
     */
    SearchWrapper select(Collection<String> fields);

    /**
     * 不查询字段
     *
     * @param field 字段名
     * @return this
     */
    default SearchWrapper noSelect(Field... field) {
        return noSelect(Objects.nonNull(field) ? Stream.of(field).map(this::getField).collect(Collectors.toList()) : null);
    }

    /**
     * 不查询字段
     *
     * @param fields 字段名集合
     * @return this
     */
    SearchWrapper noSelect(Collection<String> fields);

    /**
     * 顺序
     *
     * @param field 字段名
     * @return this
     */
    default SearchWrapper orderByAsc(Field... field) {
        return orderByAsc(null, field);
    }

    /**
     * 顺序
     *
     * @param missing 缺失字段位置 '_first'在最前，'_last'在最后
     * @param field   字段名
     * @return this
     */
    default SearchWrapper orderByAsc(Object missing, Field... field) {
        return orderByAsc(null, Objects.nonNull(field) ? Stream.of(field).map(this::getField).collect(Collectors.toList()) : null);
    }

    /**
     * 顺序
     *
     * @param fields 字段名集合
     * @return this
     */
    default SearchWrapper orderByAsc(Collection<String> fields) {
        return orderByAsc(null, fields);
    }

    /**
     * 顺序
     *
     * @param missing 缺失字段位置 '_first'在最前，'_last'在最后
     * @param fields  字段名集合
     * @return this
     */
    SearchWrapper orderByAsc(Object missing, Collection<String> fields);

    /**
     * 倒序
     *
     * @param field 字段名
     * @return this
     */
    default SearchWrapper orderByDesc(Field... field) {
        return orderByDesc(null, field);
    }

    /**
     * 倒序
     *
     * @param missing 缺失字段位置 '_first'在最前，'_last'在最后
     * @param field   字段名
     * @return this
     */
    default SearchWrapper orderByDesc(Object missing, Field... field) {
        return orderByDesc(missing, Objects.nonNull(field) ? Stream.of(field).map(this::getField).collect(Collectors.toList()) : null);
    }

    /**
     * 倒序
     *
     * @param fields 字段名集合
     * @return this
     */
    default SearchWrapper orderByDesc(Collection<String> fields) {
        return orderByDesc(null, fields);
    }

    /**
     * 倒序
     *
     * @param missing 缺失字段位置 '_first'在最前，'_last'在最后
     * @param fields  字段名集合
     * @return this
     */
    SearchWrapper orderByDesc(Object missing, Collection<String> fields);

    /**
     * 统计全部总数
     *
     * @param enabled true，统计全部总数
     * @return this
     */
    SearchWrapper trackTotalHits(Boolean enabled);

    /**
     * 定义总数上限
     *
     * @param count 总数
     * @return this
     */
    SearchWrapper trackTotalHits(Integer count);

    /**
     * 折叠
     *
     * @param field 字段名
     * @return this
     */
    SearchWrapper collapse(Field field);

    /**
     * 高亮
     *
     * @param field 字段名
     * @return this
     */
    default SearchWrapper highlight(Field... field) {
        return highlight(null, null, Objects.nonNull(field) ? Stream.of(field).map(this::getField).collect(Collectors.toList()) : null);
    }

    /**
     * 高亮
     *
     * @param fragmentSize      每个高亮的片段长度
     * @param numberOfFragments 高亮片段的长度
     * @param field             字段名
     * @return this
     */
    default SearchWrapper highlight(Integer fragmentSize, Integer numberOfFragments, Field... field) {
        return highlight(fragmentSize, numberOfFragments, Objects.nonNull(field) ? Stream.of(field).map(this::getField).collect(Collectors.toList()) : null);
    }

    /**
     * 高亮
     *
     * @param fragmentSize      每个高亮的片段长度
     * @param numberOfFragments 高亮片段的长度
     * @param fields            字段名
     * @return this
     */
    SearchWrapper highlight(Integer fragmentSize, Integer numberOfFragments, Collection<String> fields);

    /**
     * 高亮前缀
     *
     * @param val 前缀
     * @return this
     */
    SearchWrapper highlightPreTags(String... val);

    /**
     * 高亮后缀
     *
     * @param val 后缀
     * @return this
     */
    SearchWrapper highlightPostTags(String... val);

    /**
     * 自定义searchBuilder操作
     *
     * @param consumer 函数
     * @return this
     */
    SearchWrapper customSearch(Consumer<SearchBuilder> consumer);

    /**
     * 添加拼接的条件
     *
     * @param searchBuilder searchBuilder
     */
    void addSearch(SearchBuilder searchBuilder);
}
